package hyl.core.reflect;

import java.beans.IntrospectionException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.alibaba.fastjson.JSON;
import hyl.core.MyFun;
import hyl.core.io.MyFile;
import hyl.core.io.MyPath;

/**
 * @className: ReflectionUtil
 * @description: 反射工具类2,通过类名加载 ,区别于类3 都是通过对象方式加载
 * @author: gaoshuai
 * @date: 2015年8月5日 下午4:51:49
 */
public class MyRef2 {
	//private static final Logger log = LoggerFactory.getLogger(MyRef2.class);

	// public MyReflect getClass(String className) throws ClassNotFoundException {
	// ownerClass = Class.forName(className);
	// return this;
	// }
	// public MyReflect getClass(Object owner) {
	// ownerClass = owner.getClass();
	// return this;
	// }
	// class.getMethods()
	// class.getDeclaredFields()
	/**
	 * <p>
	 * Description: 把实体bean对象转为Map
	 * </p>
	 * 
	 * 
	 */
	public static Map<String, Object> bean2Map(Object bean, Map<String, Object> retMap)
			throws IntrospectionException, IllegalAccessException, InvocationTargetException {
		Class<? extends Object> clazz = bean.getClass();
		Field[] fields = clazz.getDeclaredFields();
		for (Field f : fields) {
			f.setAccessible(true);
		}
		for (Field f : fields) {
			String key = f.toString().substring(f.toString().lastIndexOf(".") + 1);
			Object value = f.get(bean);
			if (value == null)
				value = "";
			retMap.put(key, value);
		}
		return retMap;
	}

	/**
	 * 得到某类的类属性
	 * 
	 * @param className 类名
	 * @param fieldName 属性名
	 * @return 该属性对象
	 * @throws Exception
	 */
	public static Object get类中的属性(String className, String fieldName) throws Exception {
		Class<?> ownerClass = Class.forName(className);
		Field field = ownerClass.getDeclaredField(fieldName);
		Object property = field.get(ownerClass);
		return property;
	}

	/**
	 * 
	 * @title: getDeclaredMethod 不包括继承的方法
	 * @description: 获取类方法<br>
	 *               1.调用getMethods方法输出的是自身的public方法和父类Object的public方法。<br>
	 *               调用getDeclaredMethods方法输出的是自身的public、protected、private方法。<br>
	 *               2.如果想获取父类的私有函数 <br>
	 * 
	 *               ("类名","方法名", String.class, String.class)
	 */
	public static Method get方法(String 类, String 方法, Class<?>... 参数类型集合) throws ClassNotFoundException {
		Method method = null;
		Class<?> clazz = Class.forName(类);
		for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				method = clazz.getDeclaredMethod(方法, 参数类型集合);
				return method;
			} catch (Exception e) {
			}
		}
		return null;
	}

	/**
	 * 执行某类的静态方法
	 * 
	 * @param className  类名
	 * @param methodName 方法名
	 * @param args       参数数组
	 * @return 执行方法返回的结果
	 * @throws Exception
	 */
	public static Object invoke方法(String className, String methodName, Object... args) throws Exception {
		Class<?> ownerClass = Class.forName(className);
		return invoke方法(ownerClass, methodName, args);
	}

	/**
	 * <p>
	 * Title: invokeMethod
	 * </p>
	 * 
	 */
	public static Object invoke方法(Class<?> 类, String 方法, Object... 参数集合) throws Exception {
		Class<?>[] argsClass = MyReflect.getArgClasss(参数集合);
		Method method;
		if (argsClass == null) {
			method = 类.getMethod(方法);
			method.setAccessible(true);
			return method.invoke(null);
		} else {
			method = 类.getMethod(方法, argsClass);
			method.setAccessible(true);
			return method.invoke(null, 参数集合);
		}
	}

	public static Object invokeMain(Class<?> ownerClass, Object... args) throws Exception {
		String[] aa = MyFun.objArr2StrArr(args);
		Method method = ownerClass.getMethod("main", String[].class);
		// method.setAccessible(true);
		if (args == null)
			return method.invoke(null);
		else
			return method.invoke(null, (Object) aa);
	}

	/**
	 * 反射利用类构造函数新建实例
	 * 
	 * @param className 类名
	 * @param args      构造函数的参数 如果无构造参数，args 填写为 null
	 * @return 新建的实例
	 * @throws Exception
	 * @throws Exception
	 */
	public static Object newInstance(String 类名, Object[] 构造函数参数) throws Exception {
		Class<?> oneClass = Class.forName(类名);
		return newInstance(oneClass, 构造函数参数, null);
	}

	/**
	 * 反射利用类构造函数新建实例
	 * 
	 */
	public static Object newInstance(Class<?> 类, Object[] 构造函数参数) throws Exception {
		return newInstance(类, 构造函数参数, null);
	}

	/**
	 * 反射利用类构造函数新建实例
	 * 
	 * @param className 类名
	 * @param args      构造函数的参数 如果无构造参数，args 填写为 null
	 * @param argsType  Class[] classes = new Class[] { String.class, int.class };
	 * @return 新建的实例
	 * @throws Exception
	 */
	public static Object newInstance(Class<?> oneClass, Object[] args, Class<?>[] argsType)
			throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException,
			IllegalArgumentException, InvocationTargetException {
		// Class<?> oneClass = Class.forName(className);
		if (args == null) {
			return oneClass.newInstance();
		} else {
			Constructor<?> cons;// 构造函数集合
			if (argsType == null) {
				Class<?>[] argsClass = new Class[args.length];
				for (int i = 0, j = args.length; i < j; i++) {
					argsClass[i] = args[i].getClass();
				}
				cons = oneClass.getConstructor(argsClass);
			} else {
				cons = oneClass.getConstructor(argsType);
			}
			return cons.newInstance(args);
		}
	}

	/**
	 * 是不是某个类的实例
	 * 
	 * @param obj 实例
	 * @param cls 类
	 * @return 如果 obj 是此类的实例，则返回 true
	 */
	public static boolean isInstance(Object obj, Class<?> cls) {
		return cls.isInstance(obj);
	}

	/**
	 * 
	 * @description: 获取包下的所有Class
	 * @param pPackage
	 * @return: Class<?>
	 */
	public static Class<?> getClassesByPackage(String 包名) {
		Package _Package = Package.getPackage(包名);
		Class<?> _List = _Package.getClass();

		return _List;
	}

	/**
	 * <p>
	 * Title: getJarClass 静态方式获取类
	 * </p>
	 * <p>
	 * Description:
	 * 
	 * </p>
	 * 
	 * @param jarFile         从classes 文件夹中查找
	 * @param packname        指定类所在的包
	 * @param filterClassname ==null 那么就取该包下面所有的类
	 * @throws IOException
	 * @return :Map<String,Class<?>>
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings("resource")
	public static Map<String, Class<?>> getJarClass(String jarFile, String packname, String filterClassname)
			throws IOException, ClassNotFoundException {
		URLClassLoader myClassLoader = new URLClassLoader(new URL[] { MyFile.getUrl(jarFile) });
		JarFile jar = new JarFile(jarFile);
		// 返回zip文件条目的枚举
		Enumeration<JarEntry> enumFiles = jar.entries();
		JarEntry entry;
		Map<String, Class<?>> mp = new HashMap<String, Class<?>>();
		// 测试此枚举是否包含更多的元素
		while (enumFiles.hasMoreElements()) {
			entry = (JarEntry) enumFiles.nextElement();
			if (entry.getName().indexOf("META-INF") < 0) {
				String classFullName = entry.getName();
				if (classFullName.indexOf(".class") < 0) {
					classFullName = classFullName.substring(0, classFullName.length() - 1);
					continue;
				} else {
					// 去掉后缀.class
					String classPath = classFullName.substring(0, classFullName.length() - 6).replace("/", ".");
					// System.out.println("cc:"+className);
					if (classPath.indexOf(packname) == 0) {
						String className = classPath.substring(packname.length() + 1);
						// System.out.println("ddd:"+className);
						if (MyFun.isEmpty(className))
							continue;
						if (!MyFun.isEmpty(filterClassname) && className.indexOf(filterClassname) < 0)
							continue;

						Class<?> myclass = myClassLoader.loadClass(classPath);
						// System.out.println("eee:"+className);
						mp.put(className, myclass);

					}
				}
			}
		}
		return mp;
	}

	/**
	 * 只读取一个与目标类完全一致的类
	 * 
	 * @throws ClassNotFoundException
	 * 
	 */
	@SuppressWarnings("resource")
	public static Class<?> getJarClass(String jarFile, String tagclasspath) throws IOException, ClassNotFoundException {
		// 通过将给定路径名字符串转换为抽象路径名来创建一个新File实例
		// 通过jarFile和JarEntry得到所有的类
		// 返回zip文件条目的枚举
		if (MyFun.isEmpty(tagclasspath))
			throw new IOException("缺少类名");
		URLClassLoader myClassLoader = new URLClassLoader(new URL[] { MyFile.getUrl(jarFile) });
//		for(URL u:myClassLoader.getURLs() ) {
//			System.out.println(u.getPath());
//		}
//		
		String classPath = MyPath.uri2PackPath(tagclasspath);
		Class<?> myclass = myClassLoader.loadClass(classPath);
		return myclass;

	}

	/**
	 * 新建一个类环境, 动态载入jar包
	 * 
	 */
	public static URLClassLoader loadJar2Thread(String jarPath, Thread thread) throws IOException {
		// 这两个基本等价
		return new URLClassLoader(new URL[] { MyFile.getUrl(jarPath) }, thread.getContextClassLoader());
	}

	/**
	 * 添加jar 到项目中<br>
	 * 任何以“/”结尾的URL都被认为是指一个目录。否则，URL将被假定为引用一个JAR文件，该文件将被下载并根据需要打开
	 * 
	 * @param jarPath
	 * @return
	 * @throws IOException
	 */
	public static URLClassLoader loadJar(String jarPath) throws IOException {
		// 这两个基本等价
		return new URLClassLoader(new URL[] { MyFile.getUrl(jarPath) }, URLClassLoader.getSystemClassLoader());
	}

	/**
	 * 添加jar 到 父类环境
	 * 
	 * @param jarPath
	 * @param 父类环境
	 * @return
	 * @throws IOException
	 */
	public static URLClassLoader loadJar2Parent(String jarPath, URLClassLoader 父类环境) throws IOException {
		return new URLClassLoader(new URL[] { MyFile.getUrl(jarPath) }, 父类环境);
	}

	/**
	 * 根据List<Map<String, Object>>数据转换为实体Bean数据
	 * 
	 * @param datas
	 * @param beanClass
	 * @return
	 * @throws CommonException
	 */
	public static <T> List<T> ListMap2Bean(List<Map<String, Object>> datas, Class<T> beanClass) throws Exception {
		List<T> list = JSON.parseArray(JSON.toJSONString(datas), beanClass);
		// 返回
		return list;
	}

}